package com.smart.utils;

import com.smart.entity.*;
import com.smart.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Component
public class ScheduleTask {
    @Autowired
    private IEmployeeService employeeService;
    @Autowired
    private ISensorService sensorService;
    @Autowired
    private IEnvironmentDataService environmentDataService;
    @Autowired
    private IViolationRecordsService violationRecordsService;
    @Autowired
    private IDeviceService deviceService;
    @Autowired
    private IMachineSituationService machineSituationService;
    private Random random = new Random();
    private DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private final Integer number = 6;

    private List<Integer> generateRandomNumber(Integer count, Integer total, Integer change) {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            Integer randomNum = random.nextInt(change) + 1;
            if (number == randomNum) {
                while (true) {
                    Integer num = random.nextInt(total);
                    if (!list.contains(num)) {
                        list.add(num);
                        break;
                    }
                }
            }
        }
        return list;
    }

    private String getCurrentTime() {
        return LocalDateTime.now().format(formatter);
    }

    // 每日0:05执行删除15天前环境数据任务
    @Scheduled(cron = "0 5 0 * * ?")
    public void deleteEnvironmentDataTask() {
        System.out.println(getCurrentTime() + ": 删除环境数据任务开始执行...");
        environmentDataService.lambdaUpdate()
                .lt(EnvironmentData::getDeviceTime, LocalDateTime.now().minusDays(15))
                .remove();
        System.out.println("删除环境数据任务执行完毕...");
    }

    // 每日0:10执行签到情况迁移任务
    @Scheduled(cron = "0 10 0 * * ?")
    public void attendanceMigrateTask() {
        System.out.println(getCurrentTime() + ": 签到情况迁移任务开始执行...");
        List<Employee> employeeList = employeeService.lambdaQuery().list();
        for (Employee employee : employeeList) {
            employeeService.lambdaUpdate()
                    .set(Employee::getSignInYesterday, employee.getSignIn())
                    .set(Employee::getSignOutYesterday, employee.getSignOut())
                    .set(Employee::getSignIn, null)
                    .set(Employee::getSignOut, null)
                    .eq(Employee::getId, employee.getId())
                    .update();
        }
        System.out.println("签到情况迁移任务执行完毕...");
    }

    // 每日8:30执行签到任务
    @Scheduled(cron = "0 30 8 * * ?")
    public void signInTask() {
        System.out.println(getCurrentTime() + ": 签到任务开始执行...");
        List<Employee> employeeList = employeeService.lambdaQuery().list();
        List<String> abnormalSignInList = Arrays.asList("迟到", "请假");
        Integer size = employeeList.size();
        List<Integer> numList = generateRandomNumber(size, size, 10);
        employeeService.lambdaUpdate()
                .set(Employee::getSignIn, "正常")
                .update();
        for (Integer num : numList) {
            Employee employee = employeeList.get(num);
            System.out.println("签到异常员工: " + employee.getName());
            employee.setSignIn(abnormalSignInList.get(random.nextInt(abnormalSignInList.size())));
            employeeService.updateById(employee);
        }
        System.out.println("签到任务执行完毕...");
    }

    // 每日19:30执行签退任务
    @Scheduled(cron = "0 30 19 * * ?")
    public void signOutTask() {
        System.out.println(getCurrentTime() + ": 签退任务开始执行...");
        List<Employee> employeeList = employeeService.lambdaQuery().list();
        Integer size = employeeList.size();
        // List<Integer> abnormalList = generateRandomNumber(size / 3 + 1, size, 10);
        List<Integer> dangerList = generateRandomNumber(size / 10 + 1, size, 100);
        for (Employee employee : employeeList) {
            employee.setSignOut("请假".equals(employee.getSignIn()) ? "请假" : "正常");
            employeeService.updateById(employee);
        }
        // for (Integer num : abnormalList) {
        //     Employee employee = employeeList.get(num);
        //     System.out.println("签退异常员工: " + employee.getName());
        //     employee.setSignOut("早退");
        //     employeeService.updateById(employee);
        // }
        for (Integer num : dangerList) {
            Employee employee = employeeList.get(num);
            System.out.println("未签退员工: " + employee.getName());
            employee.setSignOut(null);
            employeeService.updateById(employee);
        }
        System.out.println("签退任务执行完毕...");
    }

    // 每日21:30执行签到情况统计
    @Scheduled(cron = "0 30 21 * * ?")
    public void attendanceCollectTask() {
        System.out.println(getCurrentTime() + ": 签到情况统计任务开始执行...");
        List<Employee> employeeList = employeeService.lambdaQuery().list();
        for (Employee employee : employeeList) {
            if (employee.getSignOut() == null) {
                employee.setSignOut("异常");
                employeeService.updateById(employee);
            }
        }
        System.out.println("签到情况统计任务执行完毕...");
    }

    // 每日8点、12点、16点、20点、0点添加环境数据
    @Scheduled(cron = "0 0 8,12,16,20,0 * * ?")
    public void environmentDataTask() {
        System.out.println(getCurrentTime() + ": 环境数据采集任务开始执行...");
        List<Sensor> sensorList = sensorService.list();
        LocalDateTime now = LocalDateTime.now();
        for (int i = 0; i < 24; i++) {
            Sensor sensor = sensorList.get(i);
            EnvironmentData environmentData = new EnvironmentData();
            environmentData.setDeviceId(sensor.getId().toString());
            environmentData.setDeviceLocation(sensor.getLocation());
            environmentData.setType(sensor.getType());
            environmentData.setDeviceTime(now);
            environmentData.setDoserate(BigDecimal.valueOf(random.nextInt(60) + 20));
            environmentDataService.save(environmentData);
        }
        System.out.println("环境数据采集任务执行完毕...");
    }

    // 每日8:00-19:00每10分钟判断并随机添加违规数据
    @Scheduled(cron = "0 0/10 8-19 * * ?")
    public void violationDataTask() {
        System.out.println(getCurrentTime() + ": 违规数据添加任务开始执行...");
        List<Employee> employeeList = employeeService.lambdaQuery().list();
        String[] areaList = {"东", "南", "西", "北"};
        Map<String, String> violationData = new HashMap<>();
        violationData.put("安全帽未佩戴", "工人未佩戴安全帽");
        violationData.put("危险区域闯入", "工人违规进入危险区域");
        violationData.put("安全绳未系", "工人在高空作业时未系安全绳");
        violationData.put("机械设备操作不当", "工人操作起重机不符合安全规范");
        violationData.put("无防护服操作", "工人在化学品作业区域未穿戴防护服");
        violationData.put("违规停放车辆", "车辆违规停放阻碍了施工区域");
        violationData.put("工地未清理", "工地材料堆放混乱，未及时清理");
        Integer size = employeeList.size();
        List<Integer> violatorList = generateRandomNumber(1, size, 100);
        for (Integer num : violatorList) {
            Employee employee = employeeList.get(num);
            ViolationRecords violationRecords = new ViolationRecords();
            int i = random.nextInt(violationData.size());
            String key = (String) violationData.keySet().toArray()[i];
            String value = violationData.get(key);
            violationRecords.setViolationType(key);
            violationRecords.setDescription(value);
            violationRecords.setViolatorUid(employee.getUid());
            violationRecords.setViolationDate(LocalDateTime.now());
            violationRecords.setViolationLocation("工地" + areaList[random.nextInt(areaList.length)] + "区");
            violationRecordsService.save(violationRecords);
        }
        System.out.println("违规数据添加任务执行完毕...");
    }

    // 每日8:00-19:00每10分钟判断并随机添加故障数据
    @Scheduled(cron = "0 0/10 8-19 * * ?")
    public void situationDataTask() {
        System.out.println(getCurrentTime() + ": 故障数据添加任务开始执行...");
        List<Device> deviceList = deviceService.lambdaQuery().list();
        String[] areaList = {"东", "南", "西", "北"};
        Map<String, String> situationData = new HashMap<>();
        situationData.put("发动机故障", "发动机启动困难或无法启动，运行时出现异常声音或震动，油耗异常增加");
        situationData.put("液压系统故障", "液压油泄漏，压力不稳定，液压缸动作缓慢或卡顿，液压泵发出异常噪音");
        situationData.put("电气系统故障", "设备无法正常通电，电路板出现故障导致控制失灵，电气元件如继电器、接触器损坏");
        situationData.put("传动系统故障", "齿轮磨损或损坏，传动带松弛或断裂，轴承损坏导致传动效率下降");
        situationData.put("制动系统故障", "制动效果减弱，制动踏板感觉软或无阻力，制动器发出尖叫声或异常磨损");
        situationData.put("冷却系统故障", "冷却液泄漏，散热器堵塞，风扇工作不正常，导致设备过热");
        situationData.put("操作控制系统故障", "操作杆或控制面板反应迟钝，传感器失效导致错误信号，控制系统软件故障");
        Integer size = deviceList.size();
        List<Integer> situationList = generateRandomNumber(1, size, 100);
        for (Integer num : situationList) {
            Device device = deviceList.get(num);
            MachineSituation machineSituation = new MachineSituation();
            int i = random.nextInt(situationData.size());
            String key = (String) situationData.keySet().toArray()[i];
            String value = situationData.get(key);
            machineSituation.setFaultType(key);
            machineSituation.setDescription(value);
            machineSituation.setDeviceType(device.getSubType());
            machineSituation.setDeviceId(device.getId().toString());
            machineSituation.setFaultTime(LocalDateTime.now());
            machineSituation.setLocation("工地" + areaList[random.nextInt(areaList.length)] + "区");
            machineSituation.setCommitPerson("系统");
            machineSituationService.save(machineSituation);
        }
        System.out.println("故障数据添加任务执行完毕...");
    }

    // 每日8:00-19:00每个小时更新一次设备位置信息
    @Scheduled(cron = "0 0 8-19 * * ?")
    public void deviceLocationTask() {
        System.out.println(getCurrentTime() + ": 设备位置信息更新任务开始执行...");
        List<Device> deviceList = deviceService.lambdaQuery().list();
        for (Device device : deviceList) {
            // 纬度范围24.622500~24.625800 经度范围118.086100~118.089600
            device.setLat(BigDecimal.valueOf(random.nextDouble() * (24.625800 - 24.622500) + 24.622500));
            device.setLng(BigDecimal.valueOf(random.nextDouble() * (118.089600 - 118.086100) + 118.086100));
            deviceService.updateById(device);
        }
        System.out.println("设备位置信息更新任务执行完毕...");
    }
}
